package com.edfapp.utils;

import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author hong
 * @description 描述
 * @time 2025/9/25 15:41
 **/
public class FieldExtremesUtils {
    /**
     * 存储字段的最大值和最小值
     */
    public static class FieldExtremes {
        private Object maxValue;
        private Object minValue;

        public FieldExtremes(Object maxValue, Object minValue) {
            this.maxValue = maxValue;
            this.minValue = minValue;
        }

        public Object getMaxValue() {
            return maxValue;
        }

        public Object getMinValue() {
            return minValue;
        }

        @Override
        public String toString() {
            return "max: " + maxValue + ", min: " + minValue;
        }
    }

    /**
     * 获取List中对象所有数值类型字段的最大值和最小值
     * @param list 数据列表
     * @param clazz 对象类型
     * @return 字段名到最大最小值的映射
     * @param <T> 泛型类型
     */
    public static <T> Map<String, FieldExtremes> getFieldExtremes(List<T> list, Class<T> clazz) {
        Map<String, FieldExtremes> result = new HashMap<>();

        if (list == null || list.isEmpty()) {
            return result;
        }

        // 获取所有数值类型的字段
        List<Field> numericFields = Arrays.stream(clazz.getDeclaredFields())
                .filter(field -> isNumericType(field.getType()))
                .collect(Collectors.toList());

        // 处理每个字段
        for (Field field : numericFields) {
            field.setAccessible(true); // 设置可访问私有字段
            String fieldName = field.getName();
            Class<?> fieldType = field.getType();

            try {
                // 提取字段值列表
                List<Object> fieldValues = new ArrayList<>();
                for (T item : list) {
                    Object value = field.get(item);
                    if (value != null) {
                        fieldValues.add(value);
                    }
                }

                if (!fieldValues.isEmpty()) {
                    // 计算最大值和最小值
                    Object max = getMaxValue(fieldValues, fieldType);
                    Object min = getMinValue(fieldValues, fieldType);
                    result.put(fieldName, new FieldExtremes(max, min));
                }
            } catch (IllegalAccessException e) {
                System.err.println("无法访问字段 " + fieldName + ": " + e.getMessage());
            }
        }

        return result;
    }

    /**
     * 判断是否为数值类型
     */
    private static boolean isNumericType(Class<?> type) {
        return type == int.class || type == long.class || type == float.class ||
                type == double.class || type == Integer.class || type == Long.class ||
                type == Float.class || type == Double.class;
    }

    /**
     * 获取最大值
     */
    private static Object getMaxValue(List<Object> values, Class<?> type) {
        if (values.isEmpty()) return null;

        if (type == int.class || type == Integer.class) {
            return values.stream().mapToInt(v -> (Integer) v).max().getAsInt();
        } else if (type == long.class || type == Long.class) {
            return values.stream().mapToLong(v -> (Long) v).max().getAsLong();
        } else if (type == float.class || type == Float.class) {
            return values.stream().mapToDouble(v -> (Float) v).max().getAsDouble();
        } else if (type == double.class || type == Double.class) {
            return values.stream().mapToDouble(v -> (Double) v).max().getAsDouble();
        }

        return null;
    }

    /**
     * 获取最小值
     */
    private static Object getMinValue(List<Object> values, Class<?> type) {
        if (values.isEmpty()) return null;

        if (type == int.class || type == Integer.class) {
            return values.stream().mapToInt(v -> (Integer) v).min().getAsInt();
        } else if (type == long.class || type == Long.class) {
            return values.stream().mapToLong(v -> (Long) v).min().getAsLong();
        } else if (type == float.class || type == Float.class) {
            return values.stream().mapToDouble(v -> (Float) v).min().getAsDouble();
        } else if (type == double.class || type == Double.class) {
            return values.stream().mapToDouble(v -> (Double) v).min().getAsDouble();
        }

        return null;
    }
}
